#include <iostream>
#include <vector>
#include <unordered_map>
#include <cstdint>
#include <functional>
#include <memory>
#include <unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask{
    private:
        uint64_t _id;               // 定时器任务对象ID
        uint32_t _timeout;          // 超时时间
        bool _canceled;             // 任务是否被取消 true表示被取消
        TaskFunc _task_cb;          // 定时器要执行的定时任务
        ReleaseFunc _release;       // 清空时间轮的对应关系
    public:
        TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb): _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}
        ~TimerTask()
        { 
            if(_canceled == false)
            _task_cb(); 
            _release(); 
        }
        void SetReleaseFunc(const ReleaseFunc &cb) { _release = cb; }
        void Cancel() { _canceled = true; }
        uint32_t DelayTime() { return _timeout; }
};

class TimeWheel{
    private:
        using PtrTask = std::shared_ptr<TimerTask>;
        using WeakTask = std::weak_ptr<TimerTask>;
        uint32_t _capacity; // 最大时间
        uint32_t _tick;     // 当前时间，走到哪释放(执行)到哪
        std::vector<std::vector<PtrTask>> _wheel;
        std::unordered_map<uint64_t, WeakTask> _timers;
    private:
        void RemoveTimer(uint64_t id)                                   // 从哈希表中移除事件
        {
            auto it = _timers.find(id);
            if(it != _timers.end())
            {
                _timers.erase(it);
            }
        }
    public:
        TimeWheel(): _capacity(60), _tick(0), _wheel(_capacity) {}
        void TaskAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)   // 新加任务
        {
            PtrTask pt(new TimerTask(id, delay, cb));
            pt->SetReleaseFunc(std::bind(&TimeWheel::RemoveTimer, this, id));
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
            _timers[id] = WeakTask(pt);
        }
        void TaskRefresh(uint64_t id)                                   // 刷新/延迟任务
        {
            auto it = _timers.find(id);
            if(it == _timers.end())
                return; // 没找到该ID对应的任务，直接返回
            PtrTask pt = it->second.lock();
            int delay = pt->DelayTime();
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
        }
        void CancelTask(uint64_t id)
        {
            auto it = _timers.find(id);
            if(it == _timers.end())
                return; // 没找到该ID对应的任务，直接返回
            PtrTask pt = it->second.lock();
            pt->Cancel();
        }
        void RunTask()
        {
            _tick = (_tick + 1) % _capacity;
            _wheel[_tick].clear();              // 清空数组自然会释放所有指针
        }
};

class Test{
public:
    Test() { std::cout << "构造" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

void DeleteTest(Test* t)
{
    delete t;
}

int main()
{
    TimeWheel tw;
    Test *t = new Test();
    tw.TaskAdd(888, 5, std::bind(DeleteTest, t));
    for(int i = 0; i < 5; i++)
    {
        sleep(1);
        std::cout << i << "秒过去了" << std::endl;
        tw.CancelTask(888);
        tw.RunTask();
    }
    while(1)
    {
        sleep(1);
        std::cout << "-----------" << std::endl;
        tw.RunTask();
    }
}